package cn.buk.qms.security;

import static cn.buk.qms.session.LoginUtil.execLoginProcess;

import cn.buk.jedis.RedisDao;
import cn.buk.tms.dao.UserDao;
import cn.buk.tms.dto.DtoLoginStatus;
import cn.buk.tms.entity.misc.User;
import cn.buk.tms.entity.misc.UserBindWeixin;
import cn.buk.qms.service.UserService;
import cn.buk.common.util.DateUtil;
import cn.buk.common.util.VerifyCodeUtil;
import com.alibaba.fastjson.JSON;
import java.io.IOException;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.filter.GenericFilterBean;

/**
 *
 * @author yfdai
 * @date 2017/1/6
 */
public class MySessionManagementFilter extends GenericFilterBean {
    public static final Logger logger = LogManager.getLogger(MySessionManagementFilter.class);

    /**
     * 应用所属企业的ID, 应用的主人
     */
    @Value("${owner_enterprise_id}")
    private int ownerId;

    @Autowired
    private RedisDao redisDao;

    @Autowired
    private UserDao userDao;

    @Autowired
    private UserService userService;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private PasswordEncoder passwordEncoder; //= new BCryptPasswordEncoder();

    public MySessionManagementFilter() {

    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;

        Object obj = request.getSession().getAttribute("SPRING_SECURITY_CONTEXT");
        if (obj == null) {
            autoLogin(request);
        }

        chain.doFilter(req, res);
    }

    /**
     * 通过cookie中的token值处理自动登录
     */
    private void autoLogin(HttpServletRequest request) {
        String token = null, userid = null, openid = null;

        Cookie[] cookies = request.getCookies();
        if (cookies == null) {
          return;
        }

        for (int i = 0; i < cookies.length; i++) {
            Cookie cookie = cookies[i];
            if ("token".equalsIgnoreCase(cookies[i].getName())) {
                token = cookies[i].getValue();
            } else if ("userid".equalsIgnoreCase(cookies[i].getName())) {
                userid = cookies[i].getValue();
            } else if ("openid".equalsIgnoreCase(cookie.getName())) {
                openid = cookie.getValue();
                // break;
            }
        }


        boolean logined = false;
        HttpSession session = request.getSession();

        if (userid != null) {
            User u = userDao.getUserByWwUserId(this.ownerId, userid);
            if (u != null) {
                try {
                    final String savePwd = u.getMd5Password() == null ? VerifyCodeUtil.MD5(u.getPassword()) : u.getMd5Password();
                    execLoginProcess(authenticationManager, session, u.getId(), u.getEnterprise().getId(), u.getUsername(), savePwd, u.getEmpname());
                    logger.info(u.getUsername() + ": auto login at " + DateUtil.getCurDateTime() + " by userid " + userid + ".");

                    logined = true;
                } catch (AuthenticationException ex) {
                    logger.warn(ex.getMessage());
                }
            }
        }

//        logger.info("openid: " + openid);
        if (!logined && openid != null) {
            UserBindWeixin o = userDao.getUserByOpenid(ownerId, openid);
            if (o == null) {
                // 自动注册用户名
                if (userService.autoCreateUserByOpenId(ownerId, openid) > 0) {
                    // 自动注册成功
                    o = userDao.getUserByOpenid(ownerId, openid);
                }
            }

            if (o != null) {
                User u = userDao.getUserById(o.getUserId());
                if (u != null) {
                    try {
                        final String savePwd = u.getMd5Password() == null ? VerifyCodeUtil.MD5(u.getPassword()) : u.getMd5Password();
                        execLoginProcess(authenticationManager, session, u.getId(), u.getEnterprise().getId(), u.getUsername(), savePwd, u.getEmpname());
                        System.out.println(u.getUsername() + ": auto login at " + DateUtil.getCurDateTime() + " by openid " + openid + ".");
                    } catch (AuthenticationException ex) {
                        logger.warn(ex.getMessage());
                    }
                }
            }
        }


        if (!logined && token != null) {
            final String tokenJson = redisDao.getStr("token:" + token);
            if (tokenJson != null) {
                DtoLoginStatus dto = JSON.parseObject(tokenJson, DtoLoginStatus.class);
                try {

//                    execLoginProcess(authenticationManager, session, dto.getUserId(), dto.getEnterpriseId(), dto.getUsername(), dto.getPassword(), dto.getFullName());
                    // It is a md5 password from the attribute password of DtoLoginStatus
                    var pwd = dto.getPassword();
                    logger.info("{}, {}, {}.", dto.getUsername(), pwd, dto.getPassword());
                    execLoginProcess(authenticationManager, session, dto.getUserId(), dto.getEnterpriseId(), dto.getUsername(), pwd, dto.getFullName());
                    logger.info(dto.getUsername() + ": auto login at " + DateUtil.getCurDateTime() + " by token " + token + ".");
                } catch (AuthenticationException ex) {
                    ex.printStackTrace();
                    logger.warn(ex.getMessage());
                }
            }
        }
    }



}
